package co.edu.udistrital;

/**
 * 
 */
public class Reloj {
	
	/**
	 * Numero de milisegundos por ciclo
	 */
	private float milisegundos;
	
	/**
	 * Ultima vez que el reloj fue actualizado
	 */
	private long ultimaActualizacion;
	
	/**
	 * Numero de ciclos que han pasado.
	 */
	private int ciclosRealizados;
	
	/**
	 * Exceso de tiempo hacia el siguiente ciclo
	 */
	private float excesoDeTiempo;
	
	/**
	 * Si se encuentra pausado el reloj o no
	 */
	private boolean pausado;
	
	/**
	 * Constructor del reloj
	 */
	public Reloj(float cilosPorSegundo) {
		setCilosPorSegundo(cilosPorSegundo);
		reiniciarReloj();
	}
	
	public void setCilosPorSegundo(float cilosPorSegundo) {
		this.milisegundos = (1.0f / cilosPorSegundo) * 1000;
	}
	
	/**
	 * Reinicia el reloj
	 */
	public void reiniciarReloj() {
		this.ciclosRealizados = 0;
		this.excesoDeTiempo = 0.0f;
		this.ultimaActualizacion = getHoraActual();
		this.pausado = false;
	}
	
	/**
	 * Actualiza el estado del reloj y sus propiedades
	 */
	public void actualizarReloj() {
		//Obtiene la actual hora y calcula la diferencia de tiempo
		long tiempoActual = getHoraActual();
		float diferenciaTiempo = (float)(tiempoActual - ultimaActualizacion) + excesoDeTiempo;
		
		//Actualiza el tiempo transucurrido y el exceso de tiempo
		if(!pausado) {
			this.ciclosRealizados += (int)Math.floor(diferenciaTiempo / milisegundos);
			this.excesoDeTiempo = diferenciaTiempo % milisegundos;
		}
		
		this.ultimaActualizacion = tiempoActual;
	}
	
	/**
	 * Pausa el reloj
	 */
	public void setPausado(boolean pausado) {
		this.pausado = pausado;
	}
	
	/**
	 * Verifica si el reloj se encuentra pausado
	 */
	public boolean estaPausado() {
		return pausado;
	}
	
	/**
	 * Comprueba si ha transcurido un ciclo de reloj, si es asi le resta uno
	 * a ciclosRealizados
	 * @return Si ha transcurrido o no un ciclo
	 */
	public boolean HaTranscurridoCiclo() {
		if(ciclosRealizados > 0) {
			this.ciclosRealizados--;
			return true;
		}
		return false;
	}
	
	/**
	 * Comprueba si ha transcurrido un ciclo de reloj sin decrementar
	 * @return Si ha transcurrido el ciclo o no
	 */
	public boolean HaTranscurridoCicloSinDecrementar() {
		return (ciclosRealizados > 0);
	}
	
	/**
	 * Calcula la hora actual en milisegundos
	 */
	private static final long getHoraActual() {
		return (System.nanoTime() / 1000000L);
	}

}
